import blue
import bluepy
import sys
import __builtin__
import os
blue.pyos.taskletTimer.active = True
sys.setmemcontextsactive(True)
GetCurrent = blue.pyos.taskletTimer.GetCurrent
ClockThis = sys.ClockThis

def Mark(context, function, *args, **kw):
    return ClockThis(context, function, *args, **kw)



def PushMark(context):
    return bluepy.PushTimer(context)


__builtin__.Mark = Mark
__builtin__.PushMark = PushMark
__builtin__.PopMark = bluepy.PopTimer
import types
from base64 import decodestring, encodestring
from cPickle import Unpickler, dumps
import cStringIO
import os
import blue.win32
import re
DEFAULT_ENCODING = 'cp1252'
os.stat_float_times(False)

def strx(o):
    try:
        return str(o)
    except UnicodeEncodeError:
        sys.exc_clear()
        return unicode(o).encode('ascii', 'replace')


__builtin__.strx = strx
import cPickle
old_Unpickler = cPickle.Unpickler

def find_global(moduleName, className):
    mod = __import__(moduleName, globals(), locals(), [])
    obj = getattr(mod, className)
    if (obj in blue.marshal.globalsWhitelist):
        return obj
    raise cPickle.UnpicklingError(('%s.%s not in whitelist' % (moduleName, className)))



def Unpickler(file):
    u = old_Unpickler(file)
    u.find_global = find_global
    return u



def load(fileObj):
    return cPickle.Unpickler(fileObj).load()



def loads(blob):
    return load(cStringIO.StringIO(blob))


cPickle.Unpickler = Unpickler
cPickle.load = load
cPickle.loads = loads

class IniFile:
    __guid__ = 'util.IniFile'
    nopickles = [types.IntType,
     types.FloatType,
     types.LongType,
     types.StringType,
     types.UnicodeType]
    nodef = [0]
    number = re.compile('[\\-]?[\\d.]+')

    def __init__(self, shortname, root = None, readOnly = 0):
        self.data = ''
        self.blocks = []
        self.keyval = {}
        if (root is None):
            root = blue.os.settingspath
        elif (root[-1] not in ('\\', '/')):
            root += '/'
        if (shortname[-4:] != '.ini'):
            filename = ((root + shortname) + '.ini')
        else:
            filename = (root + shortname)
        self.filename = filename
        self.lines = []
        filedata = None
        try:
            filedata = blue.win32.AtomicFileRead(filename)
            self.lines = filedata[0].splitlines()
        except WindowsError:
            pass
        self.readOnly = readOnly
        oldLines = self.lines
        self.lines = []
        for newLine in oldLines:
            try:
                self.lines.append(unicode(newLine, DEFAULT_ENCODING).encode(DEFAULT_ENCODING))
            except:
                print 'Unencodable data discovered in ini file. Removing offending data.'

        for line in self.lines:
            sline = line.strip()
            if (sline and (line[0] not in '[;#')):
                sep = sline.find('=')
                if (sep >= 0):
                    key = sline[:sep].strip()
                    self.keyval[key] = line




    def HasKey(self, key):
        return (self.FixKey(key) in self.keyval)



    def GetKeys(self, beginWith = None):
        if (beginWith is not None):
            beginWith = self.FixKey(beginWith)
            return [ key for key in self.keyval.keys() if (key[:len(beginWith)] == beginWith) ]
        else:
            return self.keyval.keys()



    def GetValue(self, key, default = nodef, flushDef = False):
        key = self.FixKey(key)
        if (key not in self.keyval):
            if (default is self.nodef):
                raise KeyError(key)
            if flushDef:
                self.SetValue(key, default)
            return default
        else:
            value = self.keyval[key]
            sep = value.find('=')
            value = value[(sep + 1):].strip()
            if not len(value):
                return value
            if (value.startswith('"') and value.endswith('"')):
                return unicode(value[1:-1])
            if (value[:7] == 'pickle:'):
                io = cStringIO.StringIO(value[7:].replace('\x1f', '\n'))
                return Unpickler(io).load()
            if self.number.match(value):
                try:
                    return int(value)
                except ValueError:
                    pass
                try:
                    return float(value)
                except ValueError:
                    pass
            return unicode(value)



    def SetValue(self, key, value, forcePickle = False):
        key = self.FixKey(key)
        line = self._GetLineFromFixedKeyAndValue(key, value, forcePickle)
        if (key in self.keyval):
            old = self.keyval[key]
            if (line == self.keyval[key]):
                return 
            lineno = self.lines.index(old)
            self.lines.remove(old)
            self.lines.insert(lineno, line)
        else:
            self.lines.append(line)
        self.keyval[key] = line
        self._IniFile__FlushToDisk()



    def KeyIsSpoofed(self, key):
        if (key not in self.keyval):
            return False
        else:
            oldValue = self.keyval[key]
            if (oldValue in self.lines):
                return False
            return True



    def SpoofKey(self, key, value):
        key = self.FixKey(key)
        prefs.keyval[key] = self._GetLineFromFixedKeyAndValue(key, value)



    def UnSpoofKey(self, key):
        key = self.FixKey(key)
        searchString = (key + '=')
        oldValue = None
        for line in self.lines:
            if line.startswith(searchString):
                oldValue = line
                break

        if (oldValue is None):
            if (key in self.keyval):
                del self.keyval[key]
        else:
            self.keyval[key] = oldValue



    def FixKey(self, key):
        return str(key).strip().replace('|', '||').replace('=', '-|-')



    def _GetLineFromFixedKeyAndValue(self, fixedKey, value, forcePickle = False):
        if (type(value) in types.StringTypes):
            try:
                value = value.encode(DEFAULT_ENCODING)
            except UnicodeEncodeError:
                forcePickle = True
            except UnicodeDecodeError:
                forcePickle = True
        if (forcePickle or (type(value) not in self.nopickles)):
            value = ('pickle:' + dumps(value).replace('\n', '\x1f'))
        else:
            value = unicode(value).strip()
        return ('%s=%s' % (fixedKey, value))



    def DeleteValue(self, key):
        key = self.FixKey(key)
        if (key in self.keyval):
            self.lines.remove(self.keyval[key])
            del self.keyval[key]
            self._IniFile__FlushToDisk()



    def __FlushToDisk(self):
        if (self.readOnly or (not self.filename)):
            return 
        sortlines = [ (line.lower()[:3], line) for line in self.lines ]
        sortlines.sort()
        lines = [ line[1] for line in sortlines ]
        try:
            blue.win32.AtomicFileWrite(self.filename, '\r\n'.join(lines).encode('cp1252'))
        except WindowsError:
            import log
            log.general.Log(('Failed writing %s, switching to read-only' % self.filename))
            self.readOnly = True




class Handler:

    def __init__(self, inifile):
        self.__dict__['ini'] = inifile



    def __getattr__(self, key):
        if hasattr(self.__dict__['ini'], key):
            return getattr(self.__dict__['ini'], key)
        try:
            return self.__dict__['ini'].GetValue(key)
        except KeyError:
            raise AttributeError, key



    def __setattr__(self, key, value):
        self.__dict__['ini'].SetValue(key, value)



    def __str__(self):
        return ('IniFile %s with %s entries' % (self.__dict__['ini'].filename, len(self.__dict__['ini'].keyval)))



    def __eq__(self, arg):
        return NotImplemented




def Init():
    import __builtin__
    if hasattr(__builtin__, 'prefs'):
        return 
    handler = Handler(IniFile('start', blue.os.rootpath, 1))
    __builtin__.boot = handler
    packagedClient = (blue.pyos.packaged and (handler.role == 'client'))
    commonPath = (blue.os.binpath + '../common/')
    if packagedClient:
        commonPath = blue.os.rootpath
    handler.keyval.update(IniFile('common', commonPath, 1).keyval)
    if (('/LUA:OFF' in blue.pyos.GetArg()) or (boot.GetValue('role', None) != 'client')):
        blue.os.cachepath = (blue.os.rootpath + u'cache/')
        blue.os.settingspath = (blue.os.rootpath + u'settings/')
        prefsfilepath = blue.os.cachepath.replace('\\', '/')
        for path in (blue.os.settingspath, blue.os.cachepath):
            try:
                os.makedirs(path)
            except OSError:
                pass

    else:
        import util
        cachedir = util.GetClientUniqueFolderName()
        root = (blue.win32.SHGetFolderPath(blue.win32.CSIDL_LOCAL_APPDATA) + u'\\CCP\\EVE\\')
        root = root.replace('\\', '/')
        root = ((root + cachedir) + u'/')
        blue.os.settingspath = (root + u'settings/')
        blue.os.cachepath = (root + u'cache/')
        prefsfilepath = blue.os.settingspath.replace('\\', '/')
        pre = (blue.win32.SHGetFolderPath(blue.win32.CSIDL_LOCAL_APPDATA) + u'\\CCP\\EVE\\')
        oldsettingspath = (pre + u'settings/')
        if (os.path.exists(oldsettingspath) and (not os.path.exists(blue.os.settingspath))):
            for path in (blue.os.settingspath, blue.os.cachepath):
                try:
                    os.makedirs(path)
                except OSError:
                    pass

            import shutil
            for dir in os.walk(oldsettingspath):
                for file in dir[2]:
                    src = ((dir[0] + u'\\') + file)
                    dst = (blue.os.settingspath + file)
                    shutil.copyfile(src, dst)


        for path in (blue.os.settingspath, blue.os.cachepath):
            try:
                os.makedirs(path)
            except OSError:
                pass

    handler = Handler(IniFile('prefs', prefsfilepath))
    __builtin__.prefs = handler
    sys.setdefaultencoding(DEFAULT_ENCODING)
    languageIdMap = {'00': 'en',
     '01': 'ar',
     '02': 'bg',
     '03': 'ca',
     '04': 'zh',
     '05': 'cs',
     '06': 'da',
     '07': 'de',
     '08': 'el',
     '09': 'en',
     '0a': 'es',
     '0b': 'fi',
     '0c': 'fr',
     '0d': 'iw',
     '0e': 'hu',
     '0f': 'is',
     '10': 'it',
     '11': 'ja',
     '12': 'ko',
     '13': 'nl',
     '14': 'no',
     '15': 'pl',
     '16': 'pt',
     '18': 'ro',
     '19': 'ru',
     '1a': 'hr',
     '1a': 'sr',
     '1b': 'sk',
     '1c': 'sq',
     '1d': 'sv',
     '1e': 'th',
     '1f': 'tr',
     '20': 'ur',
     '21': 'in',
     '22': 'uk',
     '23': 'be',
     '24': 'sl',
     '25': 'et',
     '26': 'lv',
     '27': 'lt',
     '2a': 'vi',
     '2b': 'hy',
     '2c': 'az',
     '2d': 'eu',
     '2f': 'mk',
     '36': 'af',
     '37': 'ka',
     '38': 'fo',
     '39': 'hi',
     '3e': 'ms'}
    v = 'HKEY_CURRENT_USER\\Control Panel\\International'
    langID = 'EN'
    try:
        locale = blue.win32.RegistryGetValue('HKEY_CURRENT_USER\\Control Panel\\International', 'Locale')
        langID = languageIdMap.get(locale[-2:].lower(), 'en').upper()
    except:
        try:
            import log
            log.LogException()
        except:
            pass
    prefs.GetValue('languageID', langID, True)
    if (boot.region == 'optic'):
        prefs.SetValue('languageID', 'ZH')
    elif (prefs.GetValue('languageID', '') == 'ZH'):
        prefs.SetValue('languageID', 'EN')
    if (boot.role == 'server'):
        if ('/proxy' in blue.pyos.GetArg()):
            boot.role = 'proxy'
        else:
            if ('/vaultgen' in blue.pyos.GetArg()):
                boot.role = 'vaultgen'
    if ((boot.role in ('proxy', 'server')) and prefs.GetValue('mpi', False)):
        import MPI


Init()

